package com.huhao.wshare.controller;

import com.huhao.wshare.dto.ApiResponse;
import com.huhao.wshare.entity.Dynamic;
import com.huhao.wshare.entity.User;
import com.huhao.wshare.repository.DynamicRepository;
import com.huhao.wshare.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("/api/files")
public class FileController {

    @Value("${wshare.file.path}")
    private String fileSavePath;

    @Value("${wshare.file.url-path}")
    private String fileUrlPath;

    @Value("${wshare.server.base-url}")
    private String serverBaseUrl;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private DynamicRepository dynamicRepository;

    // 用于在同一毫秒内上传文件时生成唯一序号
    private static final AtomicInteger counter = new AtomicInteger(0);
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");


    /**
     * 原有接口：用于上传动态相关的图片或视频
     */
    @PostMapping("/upload/dynamic")
    public ResponseEntity<ApiResponse<Map<String, String>>> uploadFileForDynamic(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "dynamicId", required = false) Long dynamicId) {

        if (file.isEmpty()) {
            return new ResponseEntity<>(ApiResponse.error(400, "上传的文件不能为空"), HttpStatus.BAD_REQUEST);
        }

        // 用户认证逻辑
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getPrincipal())) {
            return new ResponseEntity<>(ApiResponse.error(401, "用户未登录"), HttpStatus.UNAUTHORIZED);
        }
        String currentUserAccount = ((UserDetails) authentication.getPrincipal()).getUsername();
        Optional<User> userOptional = userRepository.findByAccount(currentUserAccount);
        if (userOptional.isEmpty()) {
            return new ResponseEntity<>(ApiResponse.error(404, "当前登录用户不存在"), HttpStatus.NOT_FOUND);
        }
        User currentUser = userOptional.get();

        // 仅在 dynamicId 存在时，才进行动态相关的校验
        if (dynamicId != null) {
            Optional<Dynamic> dynamicOptional = dynamicRepository.findById(dynamicId);
            if (dynamicOptional.isEmpty()) {
                return new ResponseEntity<>(ApiResponse.error(404, "指定的动态不存在"), HttpStatus.NOT_FOUND);
            }
            Dynamic dynamic = dynamicOptional.get();
            if (!dynamic.getUser().getId().equals(currentUser.getId())) {
                return new ResponseEntity<>(ApiResponse.error(403, "无权为该动态上传文件"), HttpStatus.FORBIDDEN);
            }
        }

        try {
            String fileTypeDir = getFileTypeDirectory(file);

            // 文件子路径：username/image 或 username/video
            String subPath = Paths.get(
                    currentUser.getUsername(),
                    fileTypeDir
            ).toString();

            // 创建目标目录
            Path uploadDir = Paths.get(fileSavePath).resolve(subPath);
            Files.createDirectories(uploadDir);

            // 生成新的文件名
            String originalFilename = StringUtils.cleanPath(file.getOriginalFilename());
            String fileExtension = "";
            int lastDotIndex = originalFilename.lastIndexOf(".");
            if (lastDotIndex >= 0) {
                fileExtension = originalFilename.substring(lastDotIndex);
            }
            String newFileName = generateUniqueFileName() + fileExtension;

            // 确定最终文件存储位置
            Path targetLocation = uploadDir.resolve(newFileName);

            // 保存文件
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            // 构建可访问的 URL
            String urlSafeSubPath = subPath.replace('\\', '/');
            String fileAccessUrl = ServletUriComponentsBuilder
                    .fromHttpUrl(serverBaseUrl)
                    .path(fileUrlPath)
                    .path("/")
                    .path(urlSafeSubPath)
                    .path("/")
                    .path(newFileName)
                    .toUriString();

            Map<String, String> data = new HashMap<>();
            data.put("url", fileAccessUrl);
            ApiResponse<Map<String, String>> response = ApiResponse.success("上传成功", data);

            return ResponseEntity.ok(response);

        } catch (IOException ex) {
            ApiResponse<Map<String, String>> response = ApiResponse.error(500, "文件存储失败，服务器内部错误");
            return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    // ==========================================================================================
    // ================================    【新增接口】    ========================================
    // ==========================================================================================

    /**
     * 新增接口：用于上传用户个人头像(avatar)或背景图片(bkImg)
     * @param file 上传的图片文件
     * @param type 上传类型，必须为 "avatar" 或 "bkImg"
     * @return 包含新图片URL的响应
     */
    @PostMapping("/upload/profile")
    public ResponseEntity<ApiResponse<Map<String, String>>> uploadProfileImage(
            @RequestParam("file") MultipartFile file,
            @RequestParam("type") String type) {

        // 1. 基本校验
        if (file.isEmpty()) {
            return new ResponseEntity<>(ApiResponse.error(400, "上传的文件不能为空"), HttpStatus.BAD_REQUEST);
        }
        // 校验type参数是否合法
        if (!"avatar".equalsIgnoreCase(type) && !"bkImg".equalsIgnoreCase(type)) {
            return new ResponseEntity<>(ApiResponse.error(400, "无效的上传类型，'type'参数必须是 'avatar' 或 'bkImg'"), HttpStatus.BAD_REQUEST);
        }

        // 2. 用户认证
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getPrincipal())) {
            return new ResponseEntity<>(ApiResponse.error(401, "用户未登录"), HttpStatus.UNAUTHORIZED);
        }
        String currentUserAccount = ((UserDetails) authentication.getPrincipal()).getUsername();
        Optional<User> userOptional = userRepository.findByAccount(currentUserAccount);
        if (userOptional.isEmpty()) {
            return new ResponseEntity<>(ApiResponse.error(404, "当前登录用户不存在"), HttpStatus.NOT_FOUND);
        }
        User currentUser = userOptional.get();

        try {
            // 3. 创建专用的文件存储路径
            // 路径结构: {wshare.file.path}/{username}/profile/{type}/
            // 例如: D:/wshare/zhangsan/profile/avatar/
            String subPath = Paths.get(
                    currentUser.getUsername(),
                    "profile", // 添加一层 'profile' 目录，与动态文件区分开
                    type.toLowerCase() // 使用 'avatar' 或 'bkimg' 作为子目录
            ).toString();

            Path uploadDir = Paths.get(fileSavePath).resolve(subPath);
            Files.createDirectories(uploadDir);

            // 4. 生成唯一文件名并保存文件
            String originalFilename = StringUtils.cleanPath(file.getOriginalFilename());
            String fileExtension = "";
            int lastDotIndex = originalFilename.lastIndexOf(".");
            if (lastDotIndex >= 0) {
                fileExtension = originalFilename.substring(lastDotIndex);
            }
            String newFileName = generateUniqueFileName() + fileExtension;
            Path targetLocation = uploadDir.resolve(newFileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            // 5. 构建可访问的URL
            String urlSafeSubPath = subPath.replace('\\', '/');
            String fileAccessUrl = ServletUriComponentsBuilder
                    .fromHttpUrl(serverBaseUrl)
                    .path(fileUrlPath)
                    .path("/")
                    .path(urlSafeSubPath)
                    .path("/")
                    .path(newFileName)
                    .toUriString();

            // 6. 更新数据库中用户的 avatar 或 bkImg 字段
            if ("avatar".equalsIgnoreCase(type)) {
                currentUser.setAvatar(fileAccessUrl);
            } else { // "bkImg"
                currentUser.setBkImg(fileAccessUrl);
            }
            userRepository.save(currentUser); // 保存更新后的用户信息

            // 7. 返回成功响应
            Map<String, String> data = new HashMap<>();
            data.put("url", fileAccessUrl);
            ApiResponse<Map<String, String>> response = ApiResponse.success("个人图片上传成功", data);

            return ResponseEntity.ok(response);

        } catch (IOException ex) {
            // 建议添加日志记录
            // log.error("个人图片存储失败", ex);
            ApiResponse<Map<String, String>> response = ApiResponse.error(500, "文件存储失败，服务器内部错误");
            return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }


    /**
     * 根据文件的MIME类型或文件名后缀获取对应的目录名。
     * 优先使用MIME类型，如果MIME类型不可靠，则尝试使用文件后缀名判断。
     * @param file 上传的 MultipartFile 对象
     * @return "image", "video", 或 "other"
     */
    private String getFileTypeDirectory(MultipartFile file) {
        String contentType = file.getContentType();

        // 1. 优先根据 ContentType 判断
        if (contentType != null) {
            if (contentType.startsWith("image/")) {
                return "image";
            }
            if (contentType.startsWith("video/")) {
                return "video";
            }
        }

        // 2. 如果 ContentType 不可靠，则根据文件后缀名进行判断 (Fallback)
        String filename = file.getOriginalFilename();
        if (filename != null) {
            String extension = StringUtils.getFilenameExtension(filename.toLowerCase());
            if (extension != null) {
                switch (extension) {
                    case "png":
                    case "jpg":
                    case "jpeg":
                    case "gif":
                    case "bmp":
                    case "webp":
                        return "image";
                    case "mp4":
                    case "avi":
                    case "mov":
                    case "wmv":
                    case "flv":
                        return "video";
                }
            }
        }

        // 3. 如果都无法判断，则归为 other
        return "other";
    }

    /**
     * 生成基于时间戳和原子计数器的唯一文件名（不含扩展名）
     * @return 唯一文件名字符串
     */
    private String generateUniqueFileName() {
        String timestamp = LocalDateTime.now().format(formatter);
        int sequence = counter.getAndIncrement() % 1000;
        return String.format("%s_%03d", timestamp, sequence);
    }
}
